package com.edor.maven.plugins.util;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.SuffixFileFilter;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * Created with IntelliJ IDEA.
 * User: EAD-MASTER
 * Date: 21/07/12
 * Time: 14:34
 * To change this template use File | Settings | File Templates.
 */
public class CopierHelper {

	public List<String> getFile(String baseDir, String fileExt) {
		File dir = new File(baseDir);
		String[] files = dir.list(new SuffixFileFilter("." + fileExt));
		List<String> newFilesPath = new LinkedList<String>();
		for (String file : files) {
			newFilesPath.add(getSourcePartFromFile(file));

		}
		return newFilesPath;
	}

	/**
	 * Recursively walk a directory tree and return a List of all
	 * Files found; the List is sorted using File.compareTo().
	 *
	 * @param aStartingDir is a valid directory, which can be read.
	 */
	public List<File> getFilesAndDirectoriesListing(File aStartingDir) throws FileNotFoundException {
		validateDirectory(aStartingDir);
		List<File> result = getFileListingNoSort(aStartingDir);
		Collections.sort(result);
		return result;
	}


	private List<File> getOnlyFilesListing(File aStartingDir) throws FileNotFoundException {
		validateDirectory(aStartingDir);
		List<File> result = getOnlyFilesListingNoSort(aStartingDir);
		Collections.sort(result);
		return result;
	}


	private List<File> getOnlyFilesListingNoSort(File aStartingDir) throws FileNotFoundException {
		File[] filesAndDirs = aStartingDir.listFiles();
		List<File> result = null;
		if (filesAndDirs != null) {
			result = new ArrayList<File>(filesAndDirs.length);
			List<File> filesDirs = Arrays.asList(filesAndDirs);
			for (File file : filesDirs) {
				if (file.isFile() && !getExtension(file).isEmpty()) {
					result.add(file);
				} else {
					List<File> deeperList = getOnlyFilesListingNoSort(file);
					if (deeperList != null) {
						result.addAll(deeperList);
					}
				}
			}
		}
		return result;
	}


	public static String getExtension(File file) {
		String ext = null;
		String name = file.getName();
		int i = name.lastIndexOf('.');
		if (i > 0 && i < name.length() - 1) {
			ext = name.substring(i + 1).toLowerCase();
		}
		return ext == null ? "" : ext.equalsIgnoreCase("java") ? ext : "";
	}

	private List<File> getFileListingNoSort(File aStartingDir) throws FileNotFoundException {
		File[] filesAndDirs = aStartingDir.listFiles();
		List<File> result = null;
		if (filesAndDirs != null) {
			result = new ArrayList<File>(filesAndDirs.length);
		}
		List<File> filesDirs = null;
		if (filesAndDirs != null) {
			filesDirs = Arrays.asList(filesAndDirs);
		}
		if (filesDirs != null) {
			for (File file : filesDirs) {
				result.add(file); //always add, even if directory
				if (!file.isFile()) {
					List<File> deeperList = getFileListingNoSort(file);
					result.addAll(deeperList);
				}
			}
		}
		return result;
	}

	/** Directory is valid if it exists, does not represent a file, and can be read. */
	private void validateDirectory(File aDirectory) throws FileNotFoundException {
		if (aDirectory == null) {
			throw new IllegalArgumentException("Directory should not be null.");
		}
		if (!aDirectory.exists()) {
			throw new FileNotFoundException("Directory does not exist: " + aDirectory);
		}
		if (!aDirectory.isDirectory()) {
			throw new IllegalArgumentException("Is not a directory: " + aDirectory);
		}
		if (!aDirectory.canRead()) {
			throw new IllegalArgumentException("Directory cannot be read: " + aDirectory);
		}
	}

	public void copyFileWithSourcePathToDest(String baseDir, String destDir) throws FileNotFoundException {
		TimeWatch timeWatch = TimeWatch.start();
		final List<File> newFilesPaths = getOnlyFilesListing(new File(baseDir));
		final double scanningFilesResult = ((double) TimeUnit.NANOSECONDS.toMillis(timeWatch.time()) / 1000);
		System.out.println(MessageFormat.format("Scanning baseDir= {0} \nCompleted in {1} seconds", baseDir, scanningFilesResult));
		timeWatch = timeWatch.reset();
		for (final File newFilesPath : newFilesPaths) {
			if (newFilesPath.exists()) {
				final String sourcePartFromFile = getSourcePartFromFile(newFilesPath.getPath());
				String newFileSourcePath = destDir.endsWith("\\") ? destDir + sourcePartFromFile : destDir + "\\" + sourcePartFromFile;
				try {
					FileUtils.copyFile(newFilesPath, new File(newFileSourcePath), true);
				} catch (IOException e) {
					e.printStackTrace();

					//todo  edor >> need to test JAMon
				}
			}
		}
		final double copyingFilesResult = ((double) TimeUnit.NANOSECONDS.toMillis(timeWatch.time()) / 1000);
		System.out.println(MessageFormat.format("Copying {0} Files\nCompleted in {1} seconds", newFilesPaths.size(), copyingFilesResult));
	}

	public String getSourcePartFromFile(String origFile) {
		return origFile.substring(origFile.indexOf("src", 0));
	}
}
